今天就繼續每個分類的子項目吧
我們先檢查子項目有甚麼?
乍看之下只是普通標題
但是在更下面有"看更多內容"
點下去後就可以擷取更多標題
在這邊就可以用到puppteer的功能 page.tap()
今天就先來解決這問題
我們先新增一個class類別,儲存上次的分類物件
class Category {
name: string;
href: string;
constructor(name: string, href: string) {
this.name = name;
if (name === "" && href === undefined) return;
this.href = href;
}
}
接著我們修改上次的 getCategory 方法,把 Object 都改為 Category
async function getCategory(body: string): Promise<Array<Category>> {
let $ = await cheerio.load(body);
let data: Array<Category> = [];
await $(
"div header div div div #pnProductNav #pnProductNavContents ul.main-menu li"
).each((i: number, el: any) => {
let name: string = $(el).find("a.first-level").text();
let href: string = $(el).find("a.first-level").attr("href");
if (name === "" && href === undefined) return;
//新增物件
let tmp = new Category(name, href);
data.push(tmp);
});
return data;
}
我們再新增一個方法,負責處理子項目的資料 getCategorySubPost
async function getCategorySubPost(data: Array<Category>, page: any) {
}
這裡我們就在Main方法上加入這方法,並把data和page傳入(記得把data的object也改為Category
let data: Array<Category> = await getCategory(body);
await getCategorySubPost(data, page);
接著我們循環每個data物件
把用page轉跳到每個page
for (let index = 0; index < data.length; index++) {
const element = data[index];
await page.goto(element.href);
//等待頁面載入到頁尾的footerlet end = true;
while (end){
try {
await page.waitFor(2000);
await page.tap(
"body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
);
} catch (error) {
end = false;
}
}
await page.waitForSelector("footer");
}
接著我們得針對"看更多內容"做點選
await page.tap(
"body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
);
//我們先測試一個
break;
先跑跑看
npm run start
結果看的出他的確點選到我們要的元素
但我們不知道他的最後一次出現是甚麼時候
我們可以用try catch去包他
因為page.tap()這個方法,只能在元素可看見時才能處理
所以看不到就會報錯
所以我們把他改成 while回圈,再抓到不到元素時跳出
let end = true;
while (end){
try {
//等待幾秒不要一次抓太快,雖然這裡是已經預先載入了,不會增加server負擔
//但能增加每頁切換的速度
await page.waitFor(2000);
await page.tap(
"body div.list div#scrollable.scrollable div.container div.listContent div.wrapper div.centralContent div.statement a#SiteContent_uiViewMoreBtn"
);
} catch (error) {
end = false;
}
}
那我們再來
npm run start
就可以看到他完美的跑完我們的要求了
那下一篇再來抓資料吧
我們結果預計會用vue-cli做出一個可以顯示的畫面